import Vue from 'vue'
import TwoFAWindow from '@/components/common/TwoFAWindow'
import Cache from '../../plugins/cache'
import secure from './request.secure'
import cache from './request.cache'
import AES from '@/core/utils/aes'

const requestMethods = ['get', 'post', 'delete', 'put', 'head', 'options', 'patch', 'request']

/**
 * 处理请求头，添加2fa密码头
 *
 * @param method 请求方法
 * @param password 密码
 * @param argsArray 请求方法参数数组
 */
function handleHeaders (method, password, argsArray) {
  let config
  if (method === 'post' || method === 'put' || method === 'patch') {
    config = argsArray[2]
    if (config == null) {
      config = {}
      argsArray[2] = config
    }
  } else {
    config = argsArray[1]
    if (config == null) {
      config = {}
      argsArray[1] = config
    }
  }
  const headers = config.headers || {}
  headers['X-2fa-Password'] = AES.encrypt(password)
  config.headers = headers
}

/**
 * 开启请求缓存
 * 实现逻辑：调用twoFA后，产生axios实例的代理对象，覆盖requestMethods变量中定义的方法（如get方法）
 *  实现先打开2FA认证窗口，在点击认证窗口的【确认】按钮后获取到2FA认证密码，并将密码写入到请求头中后，再发起接口请求。
 *
 * @param props TwoFAWindow组件参数
 * @usage
 *  request
 *    // 开启2FA认证
 *    .twoFA()
 *    .[post|get|delete|put|head|options|patch|request]()
 * @returns {{isExtendsAxiosInstance: boolean}}
 */
export default function (props = {}) {
  const axiosProxy = {}
  // 覆盖请求方法，实现2FA自动认证
  for (const method of requestMethods) {
    // 获取到axios原本的请求方法
    const originalMethod = this[method]
    // 给代理对象添加请求方法
    axiosProxy[method] = function () {
      return new Promise((resolve, reject) => {
        // 从缓存中获取2FA密码
        const password = Cache.memory.get('2fa-password')
        // 记住我的情况，直接调用业务接口
        if (password != null) {
          const argsArray = [...arguments]
          handleHeaders(method, password, argsArray)
          // 执行业务接口请求
          originalMethod.apply(this, argsArray)
            .then(data => {
              resolve(data)
            })
            .catch(error => {
              reject(error)
            })
          return
        }
        // 未记住，或密码存储已超时
        // - 构建2FA认证窗口
        const TwoFaWindowVue = Vue.extend(TwoFAWindow)
        const $twoFaWindow = new TwoFaWindowVue({
          el: document.createElement('div'),
          propsData: props
        })
        // - 2FA确认
        $twoFaWindow.$on('confirm', (form) => {
          $twoFaWindow.isWorking = true
          // 补充2fa密码请求头
          const argsArray = [...arguments]
          console.log('argsArray', argsArray)
          handleHeaders(method, form.password, argsArray)
          // 执行业务接口请求
          originalMethod.apply(this, argsArray)
            .then(data => {
              $twoFaWindow.close()
              resolve(data)
            })
            .catch(error => {
              reject(error)
            })
            .finally(() => {
              $twoFaWindow.isWorking = false
            })
        })
        // - 2FA取消
        $twoFaWindow.$on('cancel', () => {
          // 标记为#ignore#不会进行全局提示
          reject(new Error('#ignore#: cancel 2fa'))
        })
        document.body.appendChild($twoFaWindow.$el)
        // - 打开2FA认证窗口
        setTimeout(() => {
          $twoFaWindow.open()
        }, 100)
      })
    }
  }
  // 支持连续调用
  axiosProxy.secure = secure
  axiosProxy.cache = cache
  return axiosProxy
}
